#include "AQtimewheel.h"
#include<iostream>
using namespace TIMEWHEEL;

timer::timer(int f, int rot, int sc, std::function<void(int)> funcin) : fd(f), next(nullptr), prev(nullptr), func(funcin)
{
    resvrout = rot;
    slc = sc;
}

timeWheel::timeWheel(int sN, int tI) : sliceNumber(sN), timeInterval(tI), nowslc(0)
{
    for (int i = 0; i < sliceNumber; i++)
    {
        slices.push_back(nullptr);
    }
}

timeWheel::~timeWheel()
{
    for (int i = 0; i < sliceNumber; i++)
    {
        timer *p = slices[sliceNumber];
        while (p)
        {
            slices[sliceNumber] = p->next;
            delete p;
            p = p->next;
        }
    }
}

timer *timeWheel::addTimer(int fd, int timeout, std::function<void(int)> func)
{
    if (timeout < 0)
        return nullptr;
    int rout, slc,tick;
    if (timeout < timeInterval)
    {
        tick=1;
    }
    else
    {
        tick=timeout/timeInterval;
        
    }
    rout = tick/ sliceNumber;
    slc = (nowslc + (tick % sliceNumber))%sliceNumber;
    timer *Timer = new timer(fd, rout, slc, func);
    if (slices[slc])
    {
        Timer->next = slices[slc];
        slices[slc]->prev = Timer;
        slices[slc] = Timer;
    }
    else
    {
        slices[slc] = Timer;
    }
        

    return slices[slc];
}

timer *timeWheel::delTimer(int slc, timer *Timer)
{
    if (Timer==nullptr)
        return nullptr;
    if (Timer==slices[slc])
    {
        slices[slc] = Timer->next;
        if(Timer->next)
            slices[slc]->prev=nullptr;
        return slices[slc];
    }
    else
    {
        timer *p = Timer->next;
        Timer->prev->next = p;
        if (p)
            Timer->next->prev = Timer->prev;
        return p;
    }
}

void timeWheel::beats()
{
    timer *p = slices[nowslc];
    while (p)
    {
        p->resvrout--;
        if (p->resvrout < 0)
        {
            p->func(p->fd);
            p = delTimer(nowslc, p);
        }
        else
            p = p->next;
    }
    nowslc = (nowslc + 1) % sliceNumber;
}